<template>
    <div>
        <el-table
            ref="tableRef"
            :data="aaTable.table.data"
            :row-key="aaTable.table.pk"
            :default-expand-all="aaTable.table.expandAll"
            v-loading="aaTable.table.loading"
            :border="true"
            stripe
            @select-all="onSelectAll"
            @select="onSelect"
            @selection-change="onSelectionChange"
            v-band="$attrs"
        >
            <template v-for="(item, key) of aaTable.table.column">
                <template v-if="item.show !== false">
                    <slot v-if="item.render === 'slot'" :name="item.slotName"></slot>
                    <el-table-column
                        v-else
                        :key="key + '-column'"
                        v-bind="item"
                        :column-key="(item['columnKey'] ? item['columnKey'] : `table-column-${item.prop}`) || shortUuid()"
                    >
                        <!-- ./fieldRender/ 文件夹内的每个组件为一种字段渲染器，组件名称为渲染器名称 -->
                        <template v-if="item.render" #default="scope">
                            <component
                                :row="scope.row"
                                :field="item"
                                :column="scope.column"
                                :index="scope.$index"
                                :is="fieldRenderer[item.render]"
                                :key="getRenderKey(key, item, scope)"
                            />
                        </template>
                    </el-table-column>
                </template>
            </template>
        </el-table>
        <div v-if="aaTable.table.pagination" class="table-pagination">
            <el-pagination
                :current-page="aaTable.table.filter!.page"
                :page-size="aaTable.table.filter!.limit"
                :page-sizes="[10, 20, 50, 100]"
                background
                layout="sizes,total, ->, prev, pager, next, jumper"
                :total="aaTable.table.total"
                @size-change="onTableSizeChange"
                @current-change="onTableCurrentChange"
            ></el-pagination>
        </div>
    </div>
</template>

<script setup lang="ts">
import type { Component } from 'vue'
import { inject, nextTick, ref } from 'vue'
import { shortUuid } from '/@/utils/random'
import aaTableClass from '/@/utils/aaTable'
import { TableInstance } from 'element-plus'

const aaTable = inject('aaTable') as aaTableClass
const tableRef = ref<TableInstance>()
const fieldRenderer: Record<string, Component> = {}
const fieldRendererComponents: Record<string, any> = import.meta.glob('./fieldRender/**.vue', { eager: true })
for (const key in fieldRendererComponents) {
    const fileName = key.replace('./fieldRender/', '').replace('.vue', '')
    fieldRenderer[fileName] = fieldRendererComponents[key].default
}

const getRenderKey = (key: number, item: TableColumn, scope: any) => {
    if (item.getRenderKey && typeof item.getRenderKey == 'function') {
        return item.getRenderKey(scope.row, item, scope.column, scope.$index)
    }
    if (item.render == 'switch') {
        return item.render + item.prop
    }
    return key + scope.$index + '-' + item.render + '-' + (item.prop ? '-' + item.prop + '-' + scope.row[item.prop] : '')
}

/*
 * 全选和取消全选
 * 实现子级同时选择和取消选中
 */
const onSelectAll = (selection: TableRow[]) => {
    if (isSelectAll(selection.map((row: TableRow) => row[aaTable.table.pk!].toString()))) {
        selection.map((row: TableRow) => {
            if (row.children) {
                selectChildren(row.children, true)
            }
        })
    } else {
        tableRef.value?.clearSelection()
    }
}

/*
 * 是否是全选操作
 * 只检查第一个元素是否被选择
 * 全选时：selectIds为所有元素的id
 * 取消全选时：selectIds为所有子元素的id
 */
const isSelectAll = (selectIds: string[]) => {
    let data = aaTable.table.data as TableRow[]
    for (const key in data) {
        return selectIds.includes(data[key][aaTable.table.pk!].toString())
    }
    return false
}

/*
 * 选择子项-递归
 */
const selectChildren = (children: TableRow[], type: boolean) => {
    children.map((j: TableRow) => {
        toggleSelection(j, type)
        if (j.children) {
            selectChildren(j.children, type)
        }
    })
}

/*
 * 执行选择操作
 */
const toggleSelection = (row: TableRow, type: boolean) => {
    if (row) {
        nextTick(() => {
            tableRef.value?.toggleRowSelection(row, type)
        })
    }
}

/*
 * 手动选择时，同时选择子级
 */
const onSelect = (selection: TableRow[], row: TableRow) => {
    if (
        selection.some((item: TableRow) => {
            return row[aaTable.table.pk!] === item[aaTable.table.pk!]
        })
    ) {
        if (row.children) {
            selectChildren(row.children, true)
        }
    } else {
        if (row.children) {
            selectChildren(row.children, false)
        }
    }
}

/*
 * 记录选择的项
 */
const onSelectionChange = (selection: TableRow[]) => {
    aaTable.onTableAction('selection-change', selection)
}

const onTableSizeChange = (value: number) => {
    aaTable.onTableAction('page-size-change', { pageSize: value })
}
const onTableCurrentChange = (value: number) => {
    aaTable.onTableAction('current-page-change', { curPage: value })
}

/*
 * 设置折叠所有-递归
 */
const setUnFoldAll = (children: TableRow[], unfold: boolean) => {
    for (const key in children) {
        tableRef.value?.toggleRowExpansion(children[key], unfold)
        if (children[key].children) {
            setUnFoldAll(children[key].children!, unfold)
        }
    }
}

/*
 * 折叠所有
 */
const unFoldAll = (unfold: boolean) => {
    setUnFoldAll(aaTable.table.data!, unfold)
}

const getRef = () => {
    return tableRef.value
}

defineExpose({
    unFoldAll,
    getRef,
})
</script>

<style lang="scss" scoped>
.table-pagination {
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    background-color: #fff;
    padding: 13px 15px;
}
</style>
